﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.IO;

namespace RotovapPlatform.Domain.Equipment.Device.Motors
{
	/// <summary>
	/// 电机位置配置集合类，用于管理各个电机的工作位置配置
	/// </summary>
	public class MotorPositionsCollection
	{
		/// <summary>
		/// 存储电机位置配置的字典，key为电机ID，value为该电机的工作位置配置字典
		/// </summary>
		private readonly Dictionary<string, Dictionary<string, MotorPositionConfig>> _motorPositions = new();

		/// <summary>
		/// 配置文件路径
		/// </summary>
		private readonly string _configFilePath = "Config/motorPositions.json";

		/// <summary>
		/// 添加或更新电机位置配置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <param name="positionName">位置名称</param>
		/// <param name="config">位置配置</param>
		public void AddOrUpdatePosition(string motorId, string positionName, MotorPositionConfig config)
		{
			if (string.IsNullOrEmpty(motorId))
				throw new ArgumentException("电机ID不能为空", nameof(motorId));

			if (string.IsNullOrEmpty(positionName))
				throw new ArgumentException("位置名称不能为空", nameof(positionName));

			if (config == null)
				throw new ArgumentNullException(nameof(config), "位置配置不能为空");

			// 确保电机ID的配置字典存在
			if (!_motorPositions.ContainsKey(motorId))
				_motorPositions[motorId] = new Dictionary<string, MotorPositionConfig>();

			// 添加或更新位置配置
			_motorPositions[motorId][positionName] = config;
		}

		/// <summary>
		/// 获取电机位置配置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <param name="positionName">位置名称</param>
		/// <returns>位置配置，如果不存在则返回null</returns>
		public MotorPositionConfig GetPosition(string motorId, string positionName)
		{
			if (string.IsNullOrEmpty(motorId) || string.IsNullOrEmpty(positionName))
				return null;

			if (!_motorPositions.ContainsKey(motorId))
				return null;

			if (!_motorPositions[motorId].ContainsKey(positionName))
				return null;

			return _motorPositions[motorId][positionName];
		}

		/// <summary>
		/// 移除电机位置配置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <param name="positionName">位置名称</param>
		/// <returns>是否成功移除</returns>
		public bool RemovePosition(string motorId, string positionName)
		{
			if (string.IsNullOrEmpty(motorId) || string.IsNullOrEmpty(positionName))
				return false;

			if (!_motorPositions.ContainsKey(motorId))
				return false;

			return _motorPositions[motorId].Remove(positionName);
		}

		/// <summary>
		/// 获取电机的所有工作位置名称
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <returns>位置名称集合</returns>
		public IEnumerable<string> GetPositionNames(string motorId)
		{
			if (string.IsNullOrEmpty(motorId) || !_motorPositions.ContainsKey(motorId))
				return Enumerable.Empty<string>();

			return _motorPositions[motorId].Keys.ToList();
		}

		/// <summary>
		/// 检查电机是否存在指定的工作位置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <param name="positionName">位置名称</param>
		/// <returns>是否存在</returns>
		public bool HasPosition(string motorId, string positionName)
		{
			if (string.IsNullOrEmpty(motorId) || string.IsNullOrEmpty(positionName))
				return false;

			if (!_motorPositions.ContainsKey(motorId))
				return false;

			return _motorPositions[motorId].ContainsKey(positionName);
		}

		/// <summary>
		/// 获取电机的所有工作位置配置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <returns>位置配置字典</returns>
		public Dictionary<string, MotorPositionConfig> GetAllPositions(string motorId)
		{
			if (string.IsNullOrEmpty(motorId) || !_motorPositions.ContainsKey(motorId))
				return new Dictionary<string, MotorPositionConfig>();

			return new Dictionary<string, MotorPositionConfig>(_motorPositions[motorId]);
		}

		/// <summary>
		/// 获取所有电机ID
		/// </summary>
		/// <returns>电机ID集合</returns>
		public IEnumerable<string> GetAllMotorIds()
		{
			return _motorPositions.Keys.ToList();
		}

		/// <summary>
		/// 从JSON字符串加载配置
		/// </summary>
		/// <param name="json">JSON字符串</param>
		public void LoadFromJson(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				Console.WriteLine("JSON字符串为空，无法加载");
				return;
			}

			try
			{
				Console.WriteLine($"开始解析JSON，长度: {json.Length}");
				if (json.Length > 100)
				{
					Console.WriteLine($"JSON内容预览: {json.Substring(0, 100)}...");
				}

				// 首先尝试解析为电机位置字典格式（MotorID -> PositionName -> PositionConfig）
				try
				{
					var positions = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, MotorPositionConfig>>>(json);
					if (positions != null && positions.Count > 0)
					{
						Console.WriteLine($"成功将JSON解析为电机位置字典格式，包含 {positions.Count} 个电机");
						_motorPositions.Clear();
						foreach (var motor in positions)
						{
							_motorPositions[motor.Key] = motor.Value;
							Console.WriteLine($"加载电机 {motor.Key} 的位置集合，包含 {motor.Value.Count} 个位置");
						}
						return; // 成功解析并加载，直接返回
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine($"以电机位置字典格式解析JSON失败: {ex.Message}");
					// 解析失败，继续尝试下一种格式
				}

				// 尝试解析为设备参数格式
				try
				{
					Console.WriteLine("尝试以设备参数格式解析JSON");
					var options = new JsonSerializerOptions
					{
						PropertyNameCaseInsensitive = true,
						AllowTrailingCommas = true,
						ReadCommentHandling = JsonCommentHandling.Skip
					};

					// 首先尝试解析完整的设备参数
					using (JsonDocument doc = JsonDocument.Parse(json))
					{
						// 检查是否包含motors节点
						if (doc.RootElement.TryGetProperty("motors", out JsonElement motorsElement) &&
							motorsElement.ValueKind == JsonValueKind.Array)
						{
							Console.WriteLine($"找到motors数组，包含 {motorsElement.GetArrayLength()} 个电机配置");

							// 清空现有数据
							_motorPositions.Clear();
							int validMotorCount = 0;
							int totalPositionCount = 0;

							// 遍历所有电机
							foreach (JsonElement motorElement in motorsElement.EnumerateArray())
							{
								// 获取电机ID
								if (!motorElement.TryGetProperty("id", out JsonElement idElement) ||
									idElement.ValueKind != JsonValueKind.String)
								{
									Console.WriteLine("跳过无效的电机配置（无ID或ID不是字符串）");
									continue;
								}

								string motorId = idElement.GetString();
								if (string.IsNullOrEmpty(motorId))
								{
									Console.WriteLine("跳过ID为空的电机配置");
									continue;
								}

								// 获取电机名称
								string motorName = "未命名电机";
								if (motorElement.TryGetProperty("name", out JsonElement nameElement) &&
									nameElement.ValueKind == JsonValueKind.String)
								{
									motorName = nameElement.GetString() ?? "未命名电机";
								}

								Console.WriteLine($"处理电机: {motorId} ({motorName})");

								// 检查是否有工作位置
								if (!motorElement.TryGetProperty("workPositions", out JsonElement workPositionsElement) ||
									workPositionsElement.ValueKind != JsonValueKind.Array)
								{
									Console.WriteLine($"电机 {motorId} 没有工作位置定义或格式无效");
									// 继续处理下一个电机，不要完全跳过
								}
								else
								{
									var positionDict = new Dictionary<string, MotorPositionConfig>();
									int positionCount = 0;

									// 遍历所有工作位置
									foreach (JsonElement posElement in workPositionsElement.EnumerateArray())
									{
										// 获取位置名称
										if (!posElement.TryGetProperty("name", out JsonElement posNameElement) ||
											posNameElement.ValueKind != JsonValueKind.String)
										{
											Console.WriteLine("跳过无效的工作位置配置（无名称或名称不是字符串）");
											continue;
										}

										string positionName = posNameElement.GetString();
										if (string.IsNullOrEmpty(positionName))
										{
											Console.WriteLine("跳过名称为空的工作位置配置");
											continue;
										}

										Console.WriteLine($"处理工作位置: {positionName}");

										// 提取位置信息
										double position = 0;
										double speed = 50;
										double acceleration = 20;
										double deceleration = 20;

										if (posElement.TryGetProperty("position", out JsonElement posValueElement) &&
											posValueElement.ValueKind == JsonValueKind.Number)
										{
											position = posValueElement.GetDouble();
										}

										if (posElement.TryGetProperty("speed", out JsonElement speedElement) &&
											speedElement.ValueKind == JsonValueKind.Number)
										{
											speed = speedElement.GetDouble();
										}

										if (posElement.TryGetProperty("acceleration", out JsonElement accElement) &&
											accElement.ValueKind == JsonValueKind.Number)
										{
											acceleration = accElement.GetDouble();
										}

										if (posElement.TryGetProperty("deceleration", out JsonElement decElement) &&
											decElement.ValueKind == JsonValueKind.Number)
										{
											deceleration = decElement.GetDouble();
										}

										// 创建位置配置
										MotorPositionConfig config = new MotorPositionConfig
										{
											Position = position,
											Speed = speed,
											Acceleration = acceleration,
											Deceleration = deceleration,
											PositionTolerance = 10.0  // 默认容差值
										};

										positionDict[positionName] = config;
										positionCount++;

										Console.WriteLine($"工作位置 {positionName} 处理完成: 位置={position}, 速度={speed}, 加速度={acceleration}, 减速度={deceleration}");
									}

									// 如果有有效的工作位置，添加到电机位置集合
									if (positionCount > 0)
									{
										_motorPositions[motorId] = positionDict;
										validMotorCount++;
										totalPositionCount += positionCount;

										Console.WriteLine($"电机 {motorId} 添加了 {positionCount} 个工作位置");
									}
									else
									{
										Console.WriteLine($"电机 {motorId} 没有有效的工作位置，跳过");
									}
								}
							}

							Console.WriteLine($"成功加载 {validMotorCount} 个电机的 {totalPositionCount} 个工作位置");
							return;
						}
						else
						{
							Console.WriteLine("JSON中未找到motors数组或格式无效");
						}
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine($"以设备参数格式解析JSON失败: {ex.Message}");
				}

				// 如果所有解析方法都失败，记录错误
				Console.WriteLine("所有JSON解析方法都失败，无法加载电机位置配置");
			}
			catch (Exception ex)
			{
				Console.WriteLine($"解析JSON时发生未处理的异常: {ex.Message}");
				Console.WriteLine($"异常堆栈: {ex.StackTrace}");
			}
		}

		/// <summary>
		/// 转换为JSON字符串
		/// </summary>
		/// <returns>JSON字符串</returns>
		public string ToJson()
		{
			return JsonSerializer.Serialize(_motorPositions);
		}

		/// <summary>
		/// 从设备参数加载配置
		/// </summary>
		/// <param name="motors">电机列表</param>
		public void LoadFromDeviceParameters(IEnumerable<DeviceParameters.Motor> motors)
		{
			Console.WriteLine("开始从设备参数加载电机位置配置");
			Console.WriteLine($"输入的电机配置数量: {motors?.Count() ?? 0}");

			_motorPositions.Clear();

			int motorCount = 0;
			int positionCount = 0;

			foreach (var motor in motors)
			{
				if (string.IsNullOrEmpty(motor.Id))
				{
					Console.WriteLine($"跳过无ID的电机配置");
					continue;
				}

				motorCount++;
				Console.WriteLine($"处理电机配置: {motor.Id} ({motor.Name})");

				var positionDict = new Dictionary<string, MotorPositionConfig>();
				if (motor.WorkPositions == null || !motor.WorkPositions.Any())
				{
					Console.WriteLine($"  电机 {motor.Id} 没有工作位置定义，将跳过");
					continue;
				}

				Console.WriteLine($"  电机 {motor.Id} 有 {motor.WorkPositions.Count} 个工作位置定义");

				foreach (var workPos in motor.WorkPositions)
				{
					if (string.IsNullOrEmpty(workPos.Name))
					{
						Console.WriteLine($"  跳过无名称的工作位置");
						continue;
					}

					positionCount++;
					Console.WriteLine($"  添加工作位置: {workPos.Name}, 位置值: {workPos.Position}");

					positionDict[workPos.Name] = new MotorPositionConfig
					{
						Position = workPos.Position,
						Speed = workPos.Speed,
						Acceleration = workPos.Acceleration,
						Deceleration = workPos.Deceleration,
						PositionTolerance = 10.0 // 默认位置容差值
					};
				}

				if (positionDict.Count > 0)
				{
					_motorPositions[motor.Id] = positionDict;
					Console.WriteLine($"  已为电机 {motor.Id} 添加 {positionDict.Count} 个工作位置");
				}
				else
				{
					Console.WriteLine($"  电机 {motor.Id} 没有有效的工作位置定义，将跳过");
				}
			}

			Console.WriteLine($"从设备参数加载电机位置配置完成，共处理了 {motorCount} 个电机，添加了 {positionCount} 个工作位置");
			Console.WriteLine($"最终成功加载了 {_motorPositions.Count} 个电机的位置配置");
		}

		/// <summary>
		/// 添加位置配置的简便方法
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <param name="positionName">位置名称</param>
		/// <param name="position">位置值</param>
		/// <param name="speed">速度</param>
		/// <param name="acceleration">加速度</param>
		/// <param name="deceleration">减速度</param>
		/// <param name="positionTolerance">位置容差</param>
		public void AddPosition(string motorId, string positionName, double position, double speed, double acceleration, double deceleration, double positionTolerance = 10.0)
		{
			var config = new MotorPositionConfig
			{
				Position = position,
				Speed = speed,
				Acceleration = acceleration,
				Deceleration = deceleration,
				PositionTolerance = positionTolerance
			};

			AddOrUpdatePosition(motorId, positionName, config);
		}

		/// <summary>
		/// 将位置集合保存到文件
		/// </summary>
		/// <param name="filePath">文件路径</param>
		/// <returns>是否保存成功</returns>
		public bool SaveToFile(string filePath = null)
		{
			string path = filePath ?? _configFilePath;

			try
			{
				Console.WriteLine($"准备将电机位置配置保存到文件: {path}");
				Console.WriteLine($"当前有 {_motorPositions.Count} 个电机的位置配置");

				// 输出每个电机的位置信息
				foreach (var motorId in _motorPositions.Keys)
				{
					Console.WriteLine($"  - 电机 {motorId}: {_motorPositions[motorId].Count} 个位置");
					foreach (var posName in _motorPositions[motorId].Keys)
					{
						var pos = _motorPositions[motorId][posName];
						Console.WriteLine($"    - 位置 {posName}: 值={pos.Position}, 速度={pos.Speed}");
					}
				}

				// 确保目录存在
				string directory = Path.GetDirectoryName(path);
				if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
				{
					Console.WriteLine($"创建目录: {directory}");
					Directory.CreateDirectory(directory);
				}

				string json = ToJson();
				Console.WriteLine($"序列化后的JSON长度: {json.Length} 字节");
				File.WriteAllText(path, json);
				Console.WriteLine($"已将电机位置配置保存到文件: {path}");
				return true;
			}
			catch (Exception ex)
			{
				Console.WriteLine($"保存电机位置配置到文件时出错: {ex.Message}");
				Console.WriteLine($"异常堆栈: {ex.StackTrace}");
				return false;
			}
		}

		/// <summary>
		/// 从文件加载位置集合
		/// </summary>
		/// <param name="filePath">文件路径</param>
		/// <returns>是否加载成功</returns>
		public bool LoadFromFile(string filePath = null)
		{
			string path = filePath ?? _configFilePath;

			try
			{
				Console.WriteLine($"尝试从文件加载电机位置配置: {path}");

				if (!File.Exists(path))
				{
					Console.WriteLine($"文件不存在: {path}");
					Console.WriteLine($"当前工作目录: {Directory.GetCurrentDirectory()}");
					return false;
				}

				string json = File.ReadAllText(path);
				Console.WriteLine($"已读取文件: {path}, 文件大小: {json.Length} 字节");

				LoadFromJson(json);

				Console.WriteLine($"成功从文件加载电机位置配置，共加载了 {_motorPositions.Count} 个电机的位置配置");

				// 输出每个电机的位置信息
				foreach (var motorId in _motorPositions.Keys)
				{
					Console.WriteLine($"  - 电机 {motorId}: {_motorPositions[motorId].Count} 个位置");
					foreach (var posName in _motorPositions[motorId].Keys)
					{
						var pos = _motorPositions[motorId][posName];
						Console.WriteLine($"    - 位置 {posName}: 值={pos.Position}, 速度={pos.Speed}");
					}
				}

				return true;
			}
			catch (Exception ex)
			{
				Console.WriteLine($"从文件加载电机位置配置时出错: {ex.Message}");
				Console.WriteLine($"异常堆栈: {ex.StackTrace}");
				return false;
			}
		}

		/// <summary>
		/// 清空所有配置
		/// </summary>
		public void Clear()
		{
			_motorPositions.Clear();
		}

		/// <summary>
		/// 检查指定电机是否已有工作位置配置
		/// </summary>
		/// <param name="motorId">电机ID</param>
		/// <returns>是否有工作位置配置</returns>
		public bool HasPositions(string motorId)
		{
			if (string.IsNullOrEmpty(motorId))
				return false;

			return _motorPositions.ContainsKey(motorId) && _motorPositions[motorId].Count > 0;
		}
	}

	/// <summary>
	/// 电机位置配置类
	/// </summary>
	public class MotorPositionConfig
	{
		/// <summary>
		/// 位置值
		/// </summary>
		public double Position { get; set; }

		/// <summary>
		/// 移动速度
		/// </summary>
		public double Speed { get; set; }

		/// <summary>
		/// 加速度
		/// </summary>
		public double Acceleration { get; set; }

		/// <summary>
		/// 减速度
		/// </summary>
		public double Deceleration { get; set; }

		/// <summary>
		/// 位置容差
		/// </summary>
		public double PositionTolerance { get; set; } = 10.0;
	}
}